//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

namespace Microsoft.Research.eResearch.WFServiceLibrary.SchedulerLogic
{
    using System;
    using System.Collections.Generic;
    using V2 = TaskScheduler;

    /// <summary>
    /// 
    /// </summary>
    public sealed class TaskFolderCollection : IEnumerable<TaskFolder>
    {
        /// <summary>
        /// 
        /// </summary>
        private V2.ITaskFolderCollection taskfolderList = null;

        private TaskFolder[] v1FolderList = null;

        /// <summary>
        /// Initializes a new instance of the <see cref="TaskFolderCollection"/> class.
        /// </summary>
        internal TaskFolderCollection()
        {
            this.v1FolderList = new TaskFolder[0];
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="TaskFolderCollection"/> class.
        /// </summary>
        /// <param name="v1Folder">The v1 folder.</param>
        internal TaskFolderCollection(TaskFolder v1Folder)
        {
            this.v1FolderList = new TaskFolder[] { v1Folder };
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="TaskFolderCollection"/> class.
        /// </summary>
        /// <param name="iCollection">The i collection.</param>
        internal TaskFolderCollection(V2.ITaskFolderCollection iCollection)
        {
            this.taskfolderList = iCollection;
        }

        /// <summary>
        /// Releases all resources used by this class.
        /// </summary>
        public void Dispose()
        {
            if (this.v1FolderList != null && this.v1FolderList.Length > 0)
            {
                this.v1FolderList[0].Dispose();
                this.v1FolderList[0] = null;
            }

            if (this.taskfolderList != null)
            {
                System.Runtime.InteropServices.Marshal.ReleaseComObject(this.taskfolderList);
            }
        }

        /// <summary>
        /// Gets the specified folder from the collection.
        /// </summary>
        /// <param name="index">The index of the folder to be retrieved.</param>
        /// <returns>A TaskFolder instance that represents the requested folder.</returns>
        public TaskFolder this[int index]
        {
            get
            {
                if (this.taskfolderList != null)
                {
                    return new TaskFolder(this.taskfolderList[++index]);
                }

                return this.v1FolderList[index];
            }
        }

        /// <summary>
        /// Gets the specified folder from the collection.
        /// </summary>
        /// <param name="path">The path of the folder to be retrieved.</param>
        /// <returns>A TaskFolder instance that represents the requested folder.</returns>
        public TaskFolder this[string path]
        {
            get
            {
                if (this.taskfolderList != null)
                {
                    return new TaskFolder(this.taskfolderList[path]);
                }

                if (this.v1FolderList != null && this.v1FolderList.Length > 0 && (path == string.Empty || path == "\\"))
                    return this.v1FolderList[0];
                throw new ArgumentException("Path not found");
            }
        }

        /// <summary>
        /// Copies the elements of the ICollection to an Array, starting at a particular Array index.
        /// </summary>
        /// <param name="array">The one-dimensional Array that is the destination of the elements copied from <see cref="ICollection{T}"/>. The Array must have zero-based indexing.</param>
        /// <param name="arrayIndex">The zero-based index in array at which copying begins.</param>
        internal void CopyTo(TaskFolder[] array, int arrayIndex)
        {
            if (arrayIndex < 0)
            {
                throw new ArgumentOutOfRangeException();
            }

            if (array == null)
            {
                throw new ArgumentNullException();
            }

            if (this.taskfolderList != null)
            {
                if (arrayIndex + this.Count > array.Length)
                {
                    throw new ArgumentException();
                }

                foreach (V2.ITaskFolder f in this.taskfolderList)
                {
                    array[arrayIndex++] = new TaskFolder(f);
                }
            }
            else
            {
                if (arrayIndex > this.v1FolderList.Length - 1)
                    throw new ArgumentException();
                this.v1FolderList.CopyTo(array, arrayIndex);
            }
        }

        /// <summary>
        /// Gets the number of items in the collection.
        /// </summary>
        public int Count
        {
            get
            {
                return (this.taskfolderList != null) ? this.taskfolderList.Count : this.v1FolderList.Length;
            }
        }

        /// <summary>
        /// Gets a list of items in a collection.
        /// </summary>
        /// <returns>Enumerated list of items in the collection.</returns>
        public IEnumerator<TaskFolder> GetEnumerator()
        {
            TaskFolder[] folderArray = new TaskFolder[this.Count];
            this.CopyTo(folderArray, 0);
            return new TaskFolderEnumerator(folderArray);
        }

        /// <summary>
        /// Returns an enumerator that iterates through a collection.
        /// </summary>
        /// <returns>
        /// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
        /// </returns>
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }

        /// <summary>
        /// 
        /// </summary>
        private class TaskFolderEnumerator : IEnumerator<TaskFolder>
        {
            /// <summary>
            /// 
            /// </summary>
            private TaskFolder[] folders = null;

            /// <summary>
            /// 
            /// </summary>
            private System.Collections.IEnumerator iEnum = null;

            /// <summary>
            /// Initializes a new instance of the <see cref="TaskFolderEnumerator"/> class.
            /// </summary>
            /// <param name="f">The f.</param>
            internal TaskFolderEnumerator(TaskFolder[] f)
            {
                this.folders = f;
                this.iEnum = f.GetEnumerator();
            }

            /// <summary>
            /// Gets the element in the collection at the current position of the enumerator.
            /// </summary>
            /// <value></value>
            /// <returns>
            /// The element in the collection at the current position of the enumerator.
            /// </returns>
            public TaskFolder Current
            {
                get { return this.iEnum.Current as TaskFolder; }
            }

            /// <summary>
            /// Gets the element in the collection at the current position of the enumerator.
            /// </summary>
            /// <value></value>
            /// <returns>
            /// The element in the collection at the current position of the enumerator.
            /// </returns>
            object System.Collections.IEnumerator.Current
            {
                get { return this.Current; }
            }

            /// <summary>
            /// Advances the enumerator to the next element of the collection.
            /// </summary>
            /// <returns>
            /// true if the enumerator was successfully advanced to the next element; false if the enumerator has passed the end of the collection.
            /// </returns>
            /// <exception cref="T:System.InvalidOperationException">
            /// The collection was modified after the enumerator was created.
            /// </exception>
            public bool MoveNext()
            {
                return this.iEnum.MoveNext();
            }

            /// <summary>
            /// Sets the enumerator to its initial position, which is before the first element in the collection.
            /// </summary>
            /// <exception cref="T:System.InvalidOperationException">
            /// The collection was modified after the enumerator was created.
            /// </exception>
            public void Reset()
            {
                this.iEnum.Reset();
            }

            #region IDisposable Members

            public void Dispose()
            {
            }

            #endregion
        }
    }
}
